﻿using System;
using System.ComponentModel.DataAnnotations;
using System.Linq;
using System.Threading.Tasks;
using Microsoft.AspNetCore.Mvc;
using Microsoft.EntityFrameworkCore;
using Microsoft.Extensions.Logging;
using Microsoft.Extensions.Options;
using PasteTimer.HttpApi.Host.Service;
using Volo.Abp.AspNetCore.Mvc;
using Z.EntityFramework.Plus;

namespace PasteTimer
{
    /// <summary>
    /// 
    /// </summary>
    [ApiController]
    [Route("/api/task/user/[action]")]
    public class UserController : AbpController
    {
        private ChannelHelper _channelHelper;

        private IPasteTimerDbContext _dbContext;

        private IAppCache _cache;

        private TaskConfig _config;

        private readonly ILogger<UserController> _logger;

        private readonly ImageHelper _imgHelper;

        /// <summary>
        /// 
        /// </summary>
        /// <param name="task"></param>
        /// <param name="dbContext"></param>
        /// <param name="cache"></param>
        /// <param name="config"></param>
        /// <param name="logger"></param>
        /// <param name="imageHelper"></param>
        public UserController(
            ChannelHelper task,
            IPasteTimerDbContext dbContext,
            IAppCache cache,
            IOptions<TaskConfig> config,
            ILogger<UserController> logger,
            ImageHelper imageHelper)
        {
            _channelHelper = task;
            _dbContext = dbContext;
            _cache = cache;
            _imgHelper = imageHelper;
            _config = config.Value;
            _logger = logger;
        }

        /// <summary>
        /// 
        /// </summary>
        /// <param name="guid"></param>
        /// <returns></returns>
        /// <exception cref="Exception"></exception>
        [HttpGet]
        public FileContentResult Code(string guid)
        {
            try
            {
                if (String.IsNullOrEmpty(guid))
                {
                    throw new PasteTimerException("验证码代码错误，guid不能为空!");
                }

                //进行特殊符号的替换工作
                if (!new System.Text.RegularExpressions.Regex("[0-9,a-z,A-Z]{16}").Match(guid).Success)
                {
                    throw new PasteTimerException("guid的位数不足，应为16位随机数，不能包含特殊符号，需要为字母和数字的组合");
                }

                if (_cache.KeyExits(string.Format(PublicString.CacheImageHead, guid))) { throw new PasteTimerException("guid不能重复使用！"); }

                //判断guid是否存在

                string code = _imgHelper.CreateVerifyCode(ImageHelper.VerifyCodeType.NumberVerifyCode);

                _cache.SetString(string.Format(PublicString.CacheImageHead, guid), code, 300);

                byte[] codeImage = _imgHelper.CreateByteByImgVerifyCode(code, 80, 36);

                return File(codeImage, @"image/jpeg");
            }
            catch (Exception exl)
            {
                _logger.LogException(exl);
                throw new PasteTimerException(exl.Message);
            }
        }

        /// <summary>
        /// 
        /// </summary>
        /// <param name="input"></param>
        /// <returns></returns>
        /// <exception cref="Exception"></exception>
        [HttpPost]
        public async Task<dynamic> Login(InputLogin input)
        {

            var codeval = await _cache.ReadStringAsync(String.Format(PublicString.CacheImageHead, input.guid));
            if (string.IsNullOrEmpty(codeval))
            {
                throw new PasteTimerException("图形验证码超时，请重新刷新！");
            }
            if (codeval != input.code)
            {
                _cache.RemoveKey(String.Format(PublicString.CacheImageHead, input.guid));
                throw new PasteTimerException("图形验证码错误，请重新输入！");
            }
            else
            {
                _cache.RemoveKey(String.Format(PublicString.CacheImageHead, input.guid));
            }

            var user = await _dbContext.UserInfo.Where(x => x.Email == input.Email).AsNoTracking().FirstOrDefaultAsync();
            if (user == null || user == default)
            {
                throw new PasteTimerException("不存在的邮箱账号，请重试！");
            }
            else
            {
                if (!user.IsEnable)
                {
                    throw new PasteTimerException("账号被封禁，请联系管理员");
                }

                if (user.PassWord != input.Password.ToMd5Lower())
                {
                    throw new PasteTimerException("密码错误，请重新输入");
                }

                if (String.IsNullOrEmpty(user.Grade))
                {
                    throw new PasteTimerException("当前账号未分配角色信息，请先分配后再试！");
                }

                //判定角色是否存在，然后读取权限列表

                //var time = DateTimeOffset.Now.ToUnixTimeSeconds();
                //var temptoken = $"{time}_{user.Id}_{_config.HeadTokenSecret}".ToMd5Lower();
                var token = user.Id.BuildToken(_config.HeadTokenSecret);

                //值需要记录这个账号对应的角色即可
                //通过二次缓存，可以读取权限列表信息
                Console.WriteLine(token);
                //缓冲72小时
                _cache.SetString(token, user.Grade, 3600 * 72);

                return new
                {
                    name = user.UserName,
                    token = token
                };

            }


        }

        /// <summary>
        /// 
        /// </summary>
        /// <returns></returns>
        /// <exception cref="Exception"></exception>
        [TypeFilter(typeof(RoleAttribute), Arguments = new object[] { "", "" })]
        [HttpGet]
        public async Task<dynamic> ReadInfo()
        {

            if (base.Request.Headers.ContainsKey("token"))
            {
                var token = base.Request.Headers["token"].ToString();
                var strs = token.Split('_');
                if (strs.Length >= 3)
                {
                    int.TryParse(strs[1], out var userid);
                    if (userid > 0)
                    {
                        var user = await _dbContext.UserInfo.Where(x => x.Id == userid).Select(x => new { Name = x.UserName, Id = x.Id }).FirstOrDefaultAsync();
                        if (user != null && user != default)
                        {
                            return user;
                        }
                        else
                        {
                            throw new PasteTimerException("无法获取个人信息，请重新登录");
                        }
                    }
                    else
                    {
                        throw new PasteTimerException("无法获取个人信息，请重新登录");
                    }
                }
                else
                {
                    throw new PasteTimerException("无法获取个人信息，请重新登录");
                }
            }
            else
            {
                throw new PasteTimerException("无法获取个人信息，请重新登录");
            }

        }

        /// <summary>
        /// 修改密码
        /// </summary>
        /// <param name="input"></param>
        /// <returns></returns>
        [HttpPost]
        [TypeFilter(typeof(RoleAttribute), Arguments = new object[] { "", "" })]
        public async Task<string> ChangePass(InputChangePass input)
        {
            var userid = ReadLoginUserId();
            var user = _dbContext.UserInfo.Where(x => x.Id == userid).FirstOrDefault();
            if (user != null && user != default)
            {
                if (!user.IsEnable)
                {
                    throw new PasteTimerException("当前账号被禁用，请联系管理人员！");
                }
                if (input.OldPass.ToMd5Lower() != user.PassWord)
                {
                    throw new PasteTimerException("旧密码错误，请重新输入！");
                }
                user.PassWord = input.NewPlass.ToMd5Lower();
                await _dbContext.SaveChangesAsync();

                var xtoken = ReadLoginUserToken();
                if (!String.IsNullOrEmpty(xtoken))
                {
                    _cache.RemoveKey(xtoken);
                }

                return "密码修改成功，请重新登陆！";
            }
            else
            {
                throw new PasteTimerException("当前账号信息有误，无法执行修改密码操作！");
            }
        }

        //获取登陆者的密钥
        private string ReadLoginUserToken()
        {
            if (HttpContext.Request.Headers.ContainsKey("xtoken"))
            {
                var xtoken = HttpContext.Request.Headers["xtoken"].ToString().Trim();
                if (xtoken.Contains("_"))
                {
                    //time_userid_token
                    var strs = xtoken.Split("_");
                    if (strs.Length == 3)
                    {
                        //这里可以按需是否需要校验时间

                        if ($"{strs[0]}_{strs[1]}_{_config.HeadTokenSecret}".ToMd5Lower() == strs[2])
                        {
                            return xtoken;
                        }
                    }
                }
            }

            return "";
        }

        //获取登陆者ID
        private int ReadLoginUserId()
        {
            if (HttpContext.Request.Headers.ContainsKey("xtoken"))
            {
                var xtoken = HttpContext.Request.Headers["xtoken"].ToString().Trim();
                if (xtoken.Contains("_"))
                {
                    //time_userid_token
                    var strs = xtoken.Split("_");
                    if (strs.Length == 3)
                    {
                        //这里可以按需是否需要校验时间

                        if ($"{strs[0]}_{strs[1]}_{_config.HeadTokenSecret}".ToMd5Lower() == strs[2])
                        {
                            int.TryParse(strs[1], out var uid);
                            return uid;
                        }
                    }
                }
            }

            return 0;
        }



    }
    /// <summary>
    /// 更改密码
    /// </summary>
    public class InputChangePass
    {
        /// <summary>
        /// 旧的密码
        /// </summary>
        [Required(ErrorMessage = "旧密码不能为空，请重新输入")]
        public string OldPass { get; set; }

        /// <summary>
        /// 新的密码
        /// </summary>
        [Required(ErrorMessage = "新密码不能为空，请重新输入!")]
        public string NewPlass { get; set; }
    }

}
